package com.cin.cma.server.pos.common.extension;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.cin.cma.common.model.finixx.base.BaseRequest;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.util.*;

/**
 *
 * @Date：2024-07-18 20:19
 */
public class Signuature {
    public static <T extends BaseRequest> String get(T model) {
        return encoder(String.format("key=%s&%s", model.getAppKey(), resolve(model)));
    }

    /**
     * 实体转换字符串
     *
     * @param model
     * @return 拼接字符串
     */
    private static String resolve(Object model) {
        if (model instanceof String || model instanceof Integer) {
            return model.toString();
        } else if (model instanceof BigDecimal) {
            DecimalFormat df = new DecimalFormat("0.000000");
            return df.format(model);
        } else if (model instanceof Boolean) {
            return model.toString().toLowerCase();
        } else if (model instanceof Iterable) {
            List<Object> objects = (List<Object>) model;
            StringBuffer stringBuffer = new StringBuffer();
            objects.forEach((item) -> {
                stringBuffer.append(resolve(item));
                stringBuffer.append("|");
            });
            return trimEnd(stringBuffer.toString(), "|");
        } else if (model instanceof Object) {
            JSONObject jsonObject = (JSONObject) JSON.toJSON(model);
            Iterator it = jsonObject.entrySet().iterator();
            SortedMap<String, Object> sortedMap = new TreeMap<>();
            while (it.hasNext()) {
                Map.Entry<String, Object> entry = (Map.Entry<String, Object>) it.next();
                if (entry.getValue() == null || "appKey".equals(entry.getKey()) || "signature".equals(entry.getKey())) {
                    continue;
                }
                if (entry.getValue() instanceof String && ((String) entry.getValue()).length() <= 0) {
                    continue;
                }
                sortedMap.put(entry.getKey().toLowerCase(), entry.getValue());
            }
            StringBuffer stringBuffer = new StringBuffer();
            sortedMap.forEach((key, value) -> {
                stringBuffer.append(key.toLowerCase());
                stringBuffer.append("=");
                stringBuffer.append(resolve(value));
                stringBuffer.append("&");
            });
            return trimEnd(stringBuffer.toString(), "&");
        } else {
            return model.toString();
        }
    }

    /**
     * 去除末尾字符串
     *
     * @param inStr  字符串
     * @param suffix 后缀
     * @return 字符串
     */
    private static String trimEnd(String inStr, String suffix) {
        if (inStr.endsWith(suffix)) {
            return trimEnd(inStr.substring(0, inStr.length() - suffix.length()), suffix);
        }
        return inStr;
    }

    /**
     * MD5签名
     *
     * @param s 字符串
     * @return MD5签名
     */
    private static String encoder(String s) {
        try {
            byte[] btInput = s.getBytes("GBK");
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : md) {
                int val = ((int) b) & 0xff;
                if (val < 16) {
                    sb.append("0");
                }
                sb.append(Integer.toHexString(val));
            }
            return sb.toString().toUpperCase();
        } catch (Exception e) {
            return null;
        }
    }
}
